模組:Navbox
-- Navbox Module -- -- * Fully CSS styled (inline styles possible but not default) -- * Supports unlimited rows -- -- By User:Tjcool007 from layton.wikia.com -------------------------------------------------------------------- local p = {} local args = {} -- Arguments passed to template local navbox -- Actual navbox --local working = {} local rownums, skiprows = {}, {} local hasrows, alt, hasData, isChild = false, false, false, false local activeSection, sections, cimage, cimageleft local colspan, rowspan local showText, hideText = 'Show', 'Hide' local langCode = mw.getContentLanguage():getCode() local localization = {} --localized strings table localization'en' = {show = 'Show', hide = 'Hide'} localization'ru' = {show = 'показать', hide = 'скрыть'} if localizationlangCode then showText = localizationlangCode'show' hideText = localizationlangCode'hide' end ------------------------------------------------ -- Title ------------------------------------------------ --- Processes the VDE links in the title -- -- @param titlecell The table cell of the title local function processVde( titlecell ) if not args.template then return end titlecell:wikitext('' .. mw.getCurrentFrame():expandTemplate({ title = 'vdelinks', args = { args.template, 'type' = 'navbox' } }) .. ) end --- Processes the main title row local function processTitle() local titlerow = mw.html.create('tr'):addClass('navbox-title') local titlecell = mw.html.create('th'):attr('colspan',colspan):attr('scope','col') if not pcall( processVde, titlecell ) then titlecell:wikitext( '!!!' ) end titlecell:wikitext( args.title or ' }' ) -- Padding local hasTemplate = args.template ~= nil local hasState = not args.state or args.state ~= 'plain' if hasTemplate ~= hasState then if hasTemplate then titlecell:addClass('navbox-title-padright') else titlecell:addClass('navbox-title-padleft') end end if args.titleclass then titlerow:addClass( args.titleclass ) end if args.titlestyle then titlecell:cssText( args.titlestyle ) end titlerow:node(titlecell) navbox:node(titlerow) end local function _addGutter( parent, incRowspan ) parent:tag('tr'):addClass('navbox-gutter'):tag('td'):attr('colspan',2) if incRowspan then rowspan = rowspan + 1 end end ------------------------------------------------ -- Above/Below ------------------------------------------------ --- Processes the above and below rows -- -- @param rowtype Either 'above' or 'below' local function processAboveBelow( rowtype ) if not argsrowtype then return end local abrow = mw.html.create('tr'):addClass('navbox-'..rowtype) local abcell = mw.html.create('td'):attr('colspan',colspan):wikitext( argsrowtype ) if args.. 'class' then abrow:addClass( args.. 'class' ) end if args.. 'style' then abcell:cssText( args.. 'style' ) end abrow:node( abcell ) _addGutter( navbox ) navbox:node( abrow ) end ------------------------------------------------ -- Main Rows ------------------------------------------------ --- Processes the images local function _processImage(row, imgtype) if not argsimgtype then return end local iclass = imgtype 'image' and 'navbox-image-right' or 'navbox-image-left' local imagecell = mw.html.create('td'):addClass('navbox-image'):addClass(iclass) local image = argsimgtype if image:sub(1,1) ~= 'then local width = args[imgtype .. 'width' or '100px' imagecell:css('width',width):wikitext('['..'.. image .. '|' .. width .. '|link=' .. (args[imgtype .. 'link' or '') .. ']]') else imagecell:css('width','0%'):wikitext(image) end if args.. 'class' then imagecell:addClass( args.. 'class' ) end if args.. 'style' then imagecell:cssText( args.. 'style' ) end row:node( imagecell ) if imgtype 'image' then cimage = imagecell else cimageleft = imagecell end end --- Closes the currently active section (if any) local function _closeCurrentSection() if not activeSection then return end local row = mw.html.create('tr'):addClass('navbox-section-row') local cell = mw.html.create('td'):attr('colspan',2) if not hasrows then _processImage(row,'imageleft') end cell:node(sectionsactiveSection) row:node(cell) local firstRow = false if not hasrows then firstRow = true hasrows = true _processImage(row,'image') end _addGutter(navbox,not firstRow) navbox:node(row) rowspan = rowspan + 1 activeSection = false hasData = false end --- Handles alternating rows -- -- @return Alternatingly returns true or false. Always returns false if alternating rows -- are disabled with "alternaterows = no" local function _alternateRow() if args.alternaterows 'no' then return false end if alt then alt = false return true else alt = true return false end end --- Process a single Header "row" -- -- @param num Number of the row to be processed local function processHeader(num) if not args'header'..num then return end _closeCurrentSection() local subtable = mw.html.create('table'):addClass('navbox-section') local headerrow = mw.html.create('tr') local header = mw.html.create('th'):addClass('navbox-header'):attr('colspan',2):attr('scope','col'):wikitext( args'header'..num ) local collapseme = args'state'..num or false local state = false if collapseme then -- Look at this one if collapseme ~= 'plain' then state = collapseme 'expanded' and 'expanded' or 'collapsed' end else -- Look at default local collapseall = args.defaultstate or false if collapseall then state = collapseall 'expanded' and 'expanded' or 'collapsed' end end if state then subtable:addClass('mw-collapsible'):attr('data-expandtext',args'expandtext'..num or args'defaultexpandtext' or showText):attr('data-collapsetext',args'collapsetext'..num or args'defaultcollapsetext' or hideText) if state 'collapsed' then subtable:addClass('mw-collapsed') end header:addClass('navbox-header-collapsible') end if args.headerclass then headerrow:addClass( args.headerclass ) end if args.headerstyle then header:cssText( args.headerstyle ) end headerrow:node(header) subtable:node(headerrow) sectionsnum = subtable activeSection = num end --- Processes a single list row -- -- @param num Number of the row to be processed local function processList(num) if not args'list'..num then return end local row = mw.html.create('tr'):addClass('navbox-row') if not hasrows and not activeSection then _processImage(row, 'imageleft') end local listcell = mw.html.create('td'):addClass('navbox-list') local hlistcell = listcell:tag('div'):addClass('hlist') local data = args'list'..num if data:sub(1,1) '*' then -- Add newlines to support lists properly hlistcell :newline() :wikitext( data ) :newline() else hlistcell:wikitext( data ) end local altRow = _alternateRow() if altRow then row:addClass( args.altrowclass or 'alt' ) local listclass = args.altlistclass or args.listclass or false if listclass then listcell:addClass( listclass ) end local liststyle = args.altliststyle or args.liststyle or false if liststyle then listcell:cssText( liststyle ) end else if args.rowclass then row:addClass( args.rowclass ) end if args.listclass then listcell:addClass( args.listclass ) end if args.liststyle then listcell:cssText( args.liststyle ) end end if args'group'..num then local groupcell = mw.html.create('th'):addClass('navbox-group'):attr('scope','row'):wikitext( args'group'..num ) if altRow then local groupclass = args.altgroupclass or args.groupclass or false if groupclass then groupcell:addClass( groupclass ) end local groupstyle = args.altgroupstyle or args.groupstyle or false if groupstyle then groupcell:cssText( groupstyle ) end else if args.groupclass then groupcell:addClass( args.groupclass ) end if args.groupstyle then groupcell:cssText( args.groupstyle ) end end row:node( groupcell ) else listcell:attr('colspan',2):addClass('no-group') end row:node( listcell ) local firstRow = false if not hasrows and not activeSection then firstRow = true hasrows = true _processImage(row, 'image') end if activeSection then local parent = sectionsactiveSection if not isChild or not firstRow then _addGutter(parent) end parent:node(row) hasData = true else if not isChild or not firstRow then _addGutter(navbox,not firstRow) end navbox:node( row ) rowspan = rowspan + 1 end end --- Processes all rows local function processRows() sections = {} for i=1,#rownums do local num = rownumsi if not skiprowsnum then processHeader(num) processList(num) end end _closeCurrentSection() if cimageleft then cimageleft:attr('rowspan',rowspan) end if cimage then cimage:attr('rowspan',rowspan) end end ------------------------------------------------ -- ARGUMENTS PREPROCESSOR -- * Extracts arguments from frame and stores them in args table -- * At the same time, checks for valid row numbers ------------------------------------------------ --- Preprocessor for the arguments. -- Will fill up the args table with the parameters from the frame grouped by their type. -- -- @param frame The frame passed to the Module. local function preProcessArgs(frame) local tmp = {} if frame mw.getCurrentFrame() then tmp = frame:getParent().args else tmp = frame end -- Storage tables local nums = {} -- Loop over all the args for k,v in pairs(tmp) do -- Skip empty args, which are useless if v ~= '' then local cat,num = tostring(k):match('^(%a+)(1-9%d*)$') if cat 'header' or cat 'list' then numsnum = true end argsk = v -- Simple copy end end colspan = args.image and 3 or 2 if args.imageleft then colspan = colspan + 1 end rowspan = 0 if args.alternaterows 'swap' then alt = true end for k, v in pairs(nums) do rownums#rownums+1 = tonumber(k) end table.sort(rownums) -- Calculate skip rows local cSection, cSkip local showall = args.showall for i=1,#rownums do local num = rownumsi if args'header'..num then cSection = true cSkip = false local showme = args'show'..num if showme 'no' then cSkip = true elseif showme 'auto' or (showme ~= 'yes' and showall ~= 'yes') then if not args'list'..num then local nextNum = rownumsi+1 cSkip = not nextNum or args'header'..nextNum -- If next has a header -> skip end end end if cSection and cSkip then skiprowsnum = true end end end ------------------------------------------------ -- MAIN FUNCTIONS ------------------------------------------------ --- Processes the arguments to create the navbox. -- -- @return A string with HTML that is the navbox. local function _navbox() -- Create the root HTML element local trim = function(s) return s and mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1") or '' end local border = args.border or trim(args1) or '' isChild = (border 'child' or border 'subgroup') if isChild then navbox = mw.html.create('table'):addClass('navbox-subgroup') else navbox = mw.html.create('table'):addClass('navbox') if args.state ~= 'plain' then navbox:addClass('mw-collapsible'):attr('data-expandtext',args'expandtext' or args'defaultexpandtext' or showText):attr('data-collapsetext',args'collapsetext' or args'defaultcollapsetext' or hideText) if args.state 'collapsed' then navbox:addClass('mw-collapsed') end end end if args.bodyclass then navbox:addClass(args.bodyclass) end if args.bodystyle then navbox:cssText(args.bodystyle) end -- Process... if not isChild then processTitle() processAboveBelow('above') processRows() processAboveBelow('below') return tostring(navbox) else processRows() local wrapper = mw.html.create() wrapper:wikitext('') wrapper:node(navbox) wrapper:wikitext(' ') return tostring(wrapper) end end --- Main module entry point. -- To be called with or directly from another module. -- -- @param frame The frame passed to the module via the #invoke. If called from another -- module directly, this should be a table with the parameter definition. function p.main(frame) -- Save the arguments in a local variable so other functions can use them. preProcessArgs(frame) return _navbox() end return p